package cn.lixufeng.user.service.impl;

import cn.lixufeng.basic.exception.BusinessException;
import cn.lixufeng.basic.utils.StrUtils;
import cn.lixufeng.user.constant.UserConstants;
import cn.lixufeng.user.domain.User;
import cn.lixufeng.user.mapper.UserMapper;
import cn.lixufeng.user.service.IVerifyCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 发验证码的Service实现类，不继承Base
 */
@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private UserMapper userMapper;

    // 注入redis模型
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 1.校验
     1.1 手机号不能为空
     1.2 手机号不能被注册
     2.判断验证码是否失效（从redis是否能拿到）key-- 业务键:phone
     2.1 拿到了
     2.1.1 判断是否过了重发时间（1分钟）如果没过就报错
     2.1.2 过了，直接使用原来的验证码
     2.2 拿不到
     2.2.1 生成新的验证码
     3.存redis，设置3分钟有效期 value--- code:时间戳
     4.发送短信
     * @param param
     */
    @Override
    public void sendVerifyCode(Map<String,String> param) {
        // param传入phone和type,通过type来分辨是注册还是的登录
        String phone = param.get("phone");
        String type = param.get("type");
        // 校验
        if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(type)){
            throw new BusinessException("参数不能为空！");
        }
        // 业务businessKey分辨业务
        String businessKey = "";
        // 注册
        if("register".equals(type)){
            // 校验手机号是否被注册
            User user = userMapper.findByPhone(phone);
            if(user != null){
                throw new BusinessException("该手机号已被注册！");
            }
            // key值例如key： business_register_prefix(分辨登录还是注册业务的前缀):13384153687
            // value:  9527(验证码code):14679321341313(时间戳)
            // 从redis中获取，看是否能拿到值
            businessKey =  UserConstants.BUSINESS_REGISTER_PREFIX + phone;
        } else if("binder".equals(type)){   // 绑定
            businessKey =  UserConstants.BUSINESS_BINDER_PREFIX + phone;
        }
        if(StringUtils.hasLength(businessKey)){
            // 如果业务key不为空就发送验证码
            this.sendCode(businessKey,type);
        }
    }

    // 通过businessKey发送验证码
    public void sendCode(String businessKey, String type){
        // 临时码
        Object codeTmp = redisTemplate.opsForValue().get(businessKey);
        // 声明一个code来保存变化的code
        String code = "";
        if(codeTmp != null){
            // 如果拿到码，校验是否过了1分钟的可重发时间
            // xxxx:xxxxxxxxxxxx，split分割：右边部分得到时间
            String timeTmp = codeTmp.toString().split(":")[1];
            // 如果没到1分钟，不能再发，用现在时间-获得码的时间
            if(System.currentTimeMillis() - Long.valueOf(timeTmp) <= 1*60*1000){
                // 如果没到1分钟
                throw new BusinessException("请勿重复发送验证码！");
            } else {
                // 如果1分钟到了，继续使用还没失效的验证码
                code = codeTmp.toString().split(":")[0];
            }
        } else {
            // 如果没拿到码，则发送新的4位验证码
            code = StrUtils.getComplexRandomString(4);
        }
        // 存到redis并且设置过期时间3分钟
        redisTemplate.opsForValue().set(
                businessKey,
                code+":"+System.currentTimeMillis(),
                3,
                TimeUnit.MINUTES);
        // 发送验证码短信
        System.out.println("您的验证码是：" + code + "。有效期3分钟！");
    }
}
